package hyl.core.safe;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.CRC32;

import hyl.core.fun.MyByte;
import hyl.core.info.MyBase64;

public class MyHash {
	static String SHA1 = "SHA-1";
	static String SHA256 = "SHA-256";
	static String MD5 = "MD5";
	String _algorithm = SHA256;
	MessageDigest messagedigest;

	public MyHash(String 算法) {
		// if(MyFun.isEmpty(v)算法)
		_algorithm = 算法;
		try {
			messagedigest = MessageDigest.getInstance(_algorithm);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

	public static MyHash getInsSHA256() {
		MyHash mh = new MyHash(SHA256);
		return mh;
	}

	public static MyHash getInsSHA1() {
		MyHash mh = new MyHash(SHA1);
		return mh;
	}

	public static MyHash getInsMD5() {
		MyHash mh = new MyHash(MD5);
		return mh;
	}

	public static MyHash getIns(String 算法) {
		MyHash mh = new MyHash(算法);
		return mh;
	}

	int i缓存大小 = 8192;

	/**
	 * hash 文件时可以设置 缓存大小提高效率 一般 8192 比较好
	 * 
	 * @param 大小
	 * @return
	 */
	public MyHash set缓存大小(int 大小) {
		if (大小 >= 1024)
			i缓存大小 = 大小;
		return this;
	}

	int i方式 = 0;

	/**
	 * 在 从 hash --> 十六进制编码方式 --> base64 过程中<br>
	 * 我们可以决定十六进制编码的方式
	 * 
	 * @param 方式
	 * @return
	 */
	public MyHash set转16进制方式(int 方式) {
		i方式 = 方式;
		return this;
	}

	/**
	 * hash成 byte[]
	 * 
	 * @param file
	 * @return
	 */
	public byte[] digest(File file) {
		try {
			byte[] buffer = new byte[i缓存大小];
			int len = 0;
			MessageDigest md = MessageDigest.getInstance(_algorithm);
			FileInputStream fis = new FileInputStream(file);
			while ((len = fis.read(buffer)) != -1) {
				md.update(buffer, 0, len);
			}
			fis.close();
			return md.digest();

		} catch (NoSuchAlgorithmException | IOException e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * hash成 byte[]
	 * 
	 * @param message
	 * @return
	 */
	public byte[] digest(String message) {
		return digest(message.getBytes());
	}

	/**
	 * hash成 byte[]
	 * 
	 * @param message
	 * @param encode
	 * @return
	 */
	public byte[] digest(String message, String encode) {
		try {
			return digest(message.getBytes(encode));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * hash成 byte[]
	 * 
	 * @param message
	 * @return
	 */
	public byte[] digest(byte[] message) {
		byte[] data = messagedigest.digest(message);
		switch (i方式) {//可扩展
		case 1:
			return MyByte.bytesToHex(data).getBytes();		
		default:
			return data;
		}
	}

	/**
	 * 验证是否一致
	 * 
	 * @param text 明文
	 * @param 密文
	 * @return true/false
	 * @throws Exception
	 */
	public boolean verify(String text, String 密文) {
		String md5Text = parse(text);
		return md5Text.equals(密文);
	}

	/**
	 * 求hash值
	 * 
	 * @param file
	 * @return base64字符串
	 */

	public String parse(File file) {
		byte[] b = digest(file);
		BigInteger bi = new BigInteger(1, b);
		return bi.toString(16);
	}

	/**
	 * 求hash值
	 * 
	 * @param message
	 * @return base64字符串
	 */
	public String parse(String message) {
		return parse(message.getBytes());
	}

	/**
	 * 求hash值
	 * 
	 * @param message
	 * @param encode  字符串编码
	 * @return base64字符串
	 */
	public String parse(String message, String encode) {
		try {
			return parse(message.getBytes(encode));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 求hash值
	 * 
	 * @param message
	 * @return base64字符串
	 */
	public String parse(byte[] message) {
		return MyBase64.encode(digest(message));
	}

	/////////////////////////////// crc32 需要用专门的 类编码//////////
	public static String getCRC32(File file) {
		CRC32 crc32 = new CRC32();
		FileInputStream fileInputStream = null;
		try {
			fileInputStream = new FileInputStream(file);
			byte[] buffer = new byte[8192];
			int length;
			while ((length = fileInputStream.read(buffer)) != -1) {
				crc32.update(buffer, 0, length);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				if (fileInputStream != null)
					fileInputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return crc32.getValue() + "";
	}

	public static String getCRC32(String content) {
		CRC32 crc32 = new CRC32();
		// ByteBuffer bb =ByteBuffer.allocate(content.length());
		crc32.update(content.getBytes());
		return crc32.getValue() + "";
	}

	public static String getCRC32(byte[] content) {
		CRC32 crc32 = new CRC32();
		// ByteBuffer bb =ByteBuffer.allocate(content.length());
		crc32.update(content);
		return crc32.getValue() + "";
	}
}
